using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Rss;

namespace CommonLibrary
{
	[ToolboxData("<{0}:RssReaderBox runat=\"server\" id=\"RssReaderBox1\" />")]
	public class RssReaderBox : WebControl
	{
		#region Private Fields
		
		private string _url;
		private int _maxItems;
		private List<RssItem> _items;
		private bool _showDescription = true;
		private bool _openNewWindow = false;
		private bool _useCache = true;
		private bool _showMoreLink = false;
		private bool _showDate = false;
		private string _dateFormat = "dd MMM yyyy HH:nn";
		private WebException _loadError;

		#endregion

		#region Public Properties

		/// <summary>
		/// Whether to cache the items
		/// </summary>
		[Category("Behaviour")]
		public bool UseCache
		{
			get { return _useCache; }
			set { _useCache = value; }
		}

		/// <summary>
		/// Open links in a new window
		/// </summary>
		[Category("Behaviour")]
		public bool OpenNewWindow
		{
			get { return _openNewWindow; }
			set { _openNewWindow = value; }
		}

		/// <summary>
		/// Show the description text next to the link
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		public bool ShowDescription
		{
			get { return _showDescription; }
			set { _showDescription = value; }
		}

		/// <summary>
		/// Show a 'more..' link at the end of the description
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		public bool ShowMoreLink
		{
			get { return _showMoreLink; }
			set { _showMoreLink = value; }
		}

		/// <summary>
		/// Whether to show the date or not
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		public bool ShowDate
		{
			get { return _showDate; }
			set { _showDate = value; }
		}

		/// <summary>
		/// A format string to display the date of each item (only meaningful if ShowDate is true)
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		public string DateFormat
		{
			get { return _dateFormat; }
			set { _dateFormat = value; }
		}

		/// <summary>
		/// The list of RssItems
		/// </summary>
		[Bindable(true)]
		[Category("Data")]
		public List<RssItem> Items
		{
			get
			{
				if (_items == null)
				{
					try
					{
						_items = (List<RssItem>)HttpContext.Current.Cache[Url];
					}
					catch (Exception) { }
				}

				if (_items == null)
				{
					try
					{
						RssFeed feedObj = RssFeed.Read(Url);
						if (feedObj != null)
						{
							if (MaxItems <= 0 || MaxItems > feedObj.Channels[0].Items.Count)
							{
								MaxItems = feedObj.Channels[0].Items.Count;
							}

							_items = new List<RssItem>(MaxItems);
							for (int i = 0; (i < MaxItems && i < feedObj.Channels[0].Items.Count); i++)
							{
								_items.Add(feedObj.Channels[0].Items[i]);
							}
						}

						HttpContext.Current.Cache[Url] = _items;
					}
					catch (WebException ex)
					{
						_loadError = ex;					}
				}
				return _items;
			}
			set { _items = value; }
		}

		/// <summary>
		/// The maximum number of items to list
		/// </summary>
		[Bindable(true)]
		[Category("Behaviour")]
		public int MaxItems
		{
			get { return _maxItems; }
			set { _maxItems = value; }
		}

		/// <summary>
		/// The url of the RSS feed
		/// </summary>
		[Bindable(true)]
		[Category("Data")]
		[DefaultValue("")]
		public string Url
		{
			get { return _url; }
			set
			{
				_url = value;
				if (!_url.StartsWith("http"))
				{
					_url = "http://" + _url;
				}
			}
		} 

		#endregion

		#region Events

		protected override void Render(HtmlTextWriter writer)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
			if (Items != null && _loadError == null)
			{
				writer.RenderBeginTag(HtmlTextWriterTag.Ul);
				foreach (RssItem item in Items)
				{
					HtmlTextWriter liwriter = new HtmlTextWriter(writer.InnerWriter);
					liwriter.RenderBeginTag(HtmlTextWriterTag.Li);

					HyperLink hl = new HyperLink();
					hl.NavigateUrl = item.Link.ToString();
					hl.Text = item.Title;
					if (OpenNewWindow)
					{
						hl.Attributes.Add("target", "_BLANK");
					}
					hl.RenderControl(liwriter);

					if (ShowDate)
					{
						Label dateSpan = new Label();
						dateSpan.CssClass = "RssPubDate";
						dateSpan.Text = item.PubDate.ToString(DateFormat);
						dateSpan.RenderControl(liwriter);
					}

					if (ShowDescription)
					{
						Label span = new Label();
						span.CssClass = "RssDescription";
						span.Text = StringTools.StripHtml(item.Description);
						
						if (ShowMoreLink)
						{
							span.Text = string.Format("{0} <a href=\"{1}\">{2}</a>", span.Text, hl.NavigateUrl, "more..");
						}
						
						if (!span.Text.Trim().StartsWith("<"))
						{
							span.RenderControl(liwriter);
						}
					}

					liwriter.RenderEndTag();
				}

			} 
			else
			{
				writer.RenderBeginTag(HtmlTextWriterTag.Div);
				writer.Write("The rss feed could not be loaded: '{0}'", _loadError);
			}
			writer.RenderEndTag();
		}

		#endregion
	}
}